package com.zzy.transaction.aop;

import com.zzy.transaction.exception.TransactionExecuteException;
import com.zzy.transaction.manager.TransactionCoordinator;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttributeSource;

import java.lang.reflect.Method;

@Slf4j
public class TransactionAdvisor implements MethodInterceptor {

    private TransactionAttributeSource transactionAttributeSource;

    public TransactionAdvisor(TransactionAttributeSource transactionAttributeSource) {
        this.transactionAttributeSource = transactionAttributeSource;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Method method = invocation.getMethod();
        TransactionAttribute transactionAttribute = this.transactionAttributeSource.getTransactionAttribute(method, invocation.getThis().getClass());
        if (transactionAttribute == null) {
            return invocation.proceed();
        }
        boolean error = TransactionCoordinator.hasError();
        if (error) {
            TransactionCoordinator.errorComplete(null);
        }
        Object result;
        try {
            result = invocation.proceed();
            TransactionCoordinator.normalComplete();
            return result;
        } catch (Throwable throwable) {
            if (!(throwable instanceof TransactionExecuteException)) {
                TransactionCoordinator.errorComplete(throwable);
            }
            throw throwable;
        }
    }
}
